package net.lab1024.sa.admin.module.business.aps.config;

import lombok.extern.slf4j.Slf4j;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.ScheduleConstraintProvider;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.ScheduleSolution;
import net.lab1024.sa.admin.module.business.aps.domain.optaplanner.Task;
import org.optaplanner.core.api.solver.SolverFactory;
import org.optaplanner.core.config.solver.SolverConfig;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import java.time.Duration;

/**
 * APS配置类
 * OptaPlanner相关配置
 *
 * @Author 1024创新实验室
 * @Date 2025-01-28
 * @Wechat zhuoda1024
 * @Email lab1024@163.com
 * @Copyright <a href="https://1024lab.net">1024创新实验室</a>
 */
@Slf4j
@Configuration
public class ApsConfig {

    /**
     * 配置OptaPlanner求解器工厂
     */
    @Bean
    public SolverFactory<ScheduleSolution> solverFactory() {
        log.info("初始化OptaPlanner求解器工厂");
        
        SolverConfig solverConfig = new SolverConfig()
                // 解决方案类
                .withSolutionClass(ScheduleSolution.class)
                // 规划实体类
                .withEntityClasses(Task.class)
                // 约束提供者
                .withConstraintProviderClass(ScheduleConstraintProvider.class)
                // 求解时间限制
                .withTerminationSpentLimit(Duration.ofMinutes(5))
                // 最佳分数限制（可选）
                .withTerminationBestScoreLimit("0hard/*soft")
                // 未改进时间限制
                .withTerminationUnimprovedSpentLimit(Duration.ofSeconds(30));
        
        // 可以添加更多配置
        // solverConfig.getConstructionHeuristicConfig()
        //     .setConstructionHeuristicType(ConstructionHeuristicType.FIRST_FIT_DECREASING);
        
        SolverFactory<ScheduleSolution> factory = SolverFactory.create(solverConfig);
        
        log.info("OptaPlanner求解器工厂初始化完成");
        return factory;
    }

    /**
     * APS系统配置属性
     */
    @Bean
    public ApsProperties apsProperties() {
        ApsProperties properties = new ApsProperties();
        properties.setMaxSolverThreads(2);
        properties.setDefaultSolverTimeLimit(Duration.ofMinutes(5));
        properties.setEnableAsyncSolving(true);
        properties.setEnableStatistics(true);
        properties.setLogLevel("INFO");
        
        log.info("APS系统配置属性初始化完成: {}", properties);
        return properties;
    }

    /**
     * APS配置属性类
     */
    public static class ApsProperties {
        /**
         * 最大求解器线程数
         */
        private int maxSolverThreads = 2;
        
        /**
         * 默认求解时间限制
         */
        private Duration defaultSolverTimeLimit = Duration.ofMinutes(5);
        
        /**
         * 是否启用异步求解
         */
        private boolean enableAsyncSolving = true;
        
        /**
         * 是否启用统计信息
         */
        private boolean enableStatistics = true;
        
        /**
         * 日志级别
         */
        private String logLevel = "INFO";
        
        /**
         * 是否启用求解器缓存
         */
        private boolean enableSolverCache = false;
        
        /**
         * 缓存大小
         */
        private int cacheSize = 10;

        // Getters and Setters
        public int getMaxSolverThreads() {
            return maxSolverThreads;
        }

        public void setMaxSolverThreads(int maxSolverThreads) {
            this.maxSolverThreads = maxSolverThreads;
        }

        public Duration getDefaultSolverTimeLimit() {
            return defaultSolverTimeLimit;
        }

        public void setDefaultSolverTimeLimit(Duration defaultSolverTimeLimit) {
            this.defaultSolverTimeLimit = defaultSolverTimeLimit;
        }

        public boolean isEnableAsyncSolving() {
            return enableAsyncSolving;
        }

        public void setEnableAsyncSolving(boolean enableAsyncSolving) {
            this.enableAsyncSolving = enableAsyncSolving;
        }

        public boolean isEnableStatistics() {
            return enableStatistics;
        }

        public void setEnableStatistics(boolean enableStatistics) {
            this.enableStatistics = enableStatistics;
        }

        public String getLogLevel() {
            return logLevel;
        }

        public void setLogLevel(String logLevel) {
            this.logLevel = logLevel;
        }

        public boolean isEnableSolverCache() {
            return enableSolverCache;
        }

        public void setEnableSolverCache(boolean enableSolverCache) {
            this.enableSolverCache = enableSolverCache;
        }

        public int getCacheSize() {
            return cacheSize;
        }

        public void setCacheSize(int cacheSize) {
            this.cacheSize = cacheSize;
        }

        @Override
        public String toString() {
            return "ApsProperties{" +
                    "maxSolverThreads=" + maxSolverThreads +
                    ", defaultSolverTimeLimit=" + defaultSolverTimeLimit +
                    ", enableAsyncSolving=" + enableAsyncSolving +
                    ", enableStatistics=" + enableStatistics +
                    ", logLevel='" + logLevel + '\'' +
                    ", enableSolverCache=" + enableSolverCache +
                    ", cacheSize=" + cacheSize +
                    '}';
        }
    }
}